package dominion.model;

import java.util.List;

import dominion.utils.Constants;

public class Player {

	private Deck library;
	private Deck discard;
	private Deck hand;
	private Deck playSpace;

	private int actions;
	private int money;
	private int buys;

	private String name;

	public Player(String name) {
		library = new Deck();
		discard = new Deck();
		hand = new Deck();
		playSpace = new Deck();
		this.name = name;
	}

	/**
	 * Adds a card to a given deck. If adding to library, the card is placed on
	 * top of the deck.
	 * 
	 * @param card
	 *            - Card to add
	 * @param deck
	 *            - Either library, hand, or discard
	 */
	public void addToDeck(Card card, String deck) {
		if (card == null)
		{
			System.out.println("WARNING: Can't add null card.");
			return;
		}
		else if (deck.equals(Constants.LIBRARY_DECK))
		{
			library.placeOnDeck(card);
		}
		else if (deck.equals(Constants.DISCARD_DECK))
		{
			discard.addToDeck(card);
		}
		else if (deck.equals(Constants.HAND))
		{
			hand.addToDeck(card);
		}
		else if (deck.equals(Constants.PLAY_SPACE))
		{
			playSpace.addToDeck(card);
		}
		else
		{
			System.out.println("INVALID DECK GIVEN IN: addToDeck(Card, String)");
			System.exit(1);
		}
	}

	public void addToDeck(List<Card> cards, String deck) {
		if (deck.equals(Constants.LIBRARY_DECK))
		{
			library.addToDeck(cards);
		}
		else if (deck.equals(Constants.DISCARD_DECK))
		{
			discard.addToDeck(cards);
		}
		else if (deck.equals(Constants.HAND))
		{
			hand.addToDeck(cards);
		}
		else if (deck.equals(Constants.PLAY_SPACE))
		{
			playSpace.addToDeck(cards);
		}
		else
		{
			System.out.println("INVALID DECK GIVEN IN: addToDeck(List<Card>, String");
			System.exit(1);
		}
	}

	/**
	 * Draws the top card from the given deck. Card IS removed by this method.
	 * 
	 * @param deck
	 *            - Deck name. Either hand, lib, or discard
	 * @return - Top of the given deck. Discard is shuffled into lib if lib is
	 *         empty. Returns null if deck is empty.
	 */
	public Card drawTopCardFromDeck(String deck) {
		Card result = null;
		if (deck.equals(Constants.LIBRARY_DECK))
		{
			if (library.isEmpty())
			{
				shuffleInDiscard();
			}
			result = library.drawTopCard();
		}
		else if (deck.equals(Constants.HAND))
		{
			result = hand.drawTopCard();
		}
		else if (deck.equals(Constants.DISCARD_DECK))
		{
			result = discard.drawTopCard();
		}
		else if (deck.equals(Constants.PLAY_SPACE))
		{
			result = playSpace.drawTopCard();
		}
		else
		{
			System.out.println("Error: Invalid deck givin in drawTopCardFromDeck(String)");
			System.exit(1);
		}
		return result;
	}

	public Card revealTopLib() {
		if (library.isEmpty())
		{
			shuffleInDiscard();
		}
		return library.revealTopCard();
	}

	public Card drawFromDeck(String cardName, String deck) {
		Card result = null;
		if (deck.equals(Constants.LIBRARY_DECK))
		{
			result = library.drawCard(cardName);
		}
		else if (deck.equals(Constants.DISCARD_DECK))
		{
			result = discard.drawCard(cardName);
		}
		else if (deck.equals(Constants.HAND))
		{
			result = hand.drawCard(cardName);
		}
		else if (deck.equals(Constants.PLAY_SPACE))
		{
			result = playSpace.drawCard(cardName);
		}
		else
		{
			System.out.println("ERROR: Invalid deck given in: drawFromDeck(String, String)");
			System.exit(1);
		}
		return result;
	}

	/**
	 * Discards all cards in the play area and in the hand.
	 */
	public void endTurn() {
		while (!playSpace.isEmpty())
		{
			addToDeck(playSpace.drawTopCard(), Constants.DISCARD_DECK);
		}
		while (!hand.isEmpty())
		{
			addToDeck(hand.drawTopCard(), Constants.DISCARD_DECK);
		}
	}

	public void drawHand() {
		if (library.size() >= 5)
		{
			addToDeck(library.drawCards(5), Constants.HAND);
		}
		else
		{
			// Don't have enough in lib and must shuffle in discard
			int drawn = 0;
			while (!library.isEmpty())
			{
				addToDeck(library.drawTopCard(), Constants.HAND);
				drawn++;
			}
			shuffleInDiscard();
			for (int i = drawn; i < 5; i++)
			{
				addToDeck(library.drawTopCard(), Constants.HAND);
			}
		}
	}

	/**
	 * Draw a card from the lib and put it into hand. If lib is empty, shuffle
	 * in discard, than draw.
	 */
	public void drawCard() {
		if (library.size() < 0)
		{
			System.out.println("ERROR: Lib should not be less than 0!");
			System.exit(1);
		}
		else if (library.size() == 0)
		{
			shuffleInDiscard();
		}
		addToDeck(library.drawTopCard(), Constants.HAND);
	}

	public void shuffleDeck(String deck) {
		if (deck.equals(Constants.LIBRARY_DECK))
		{
			library.shuffle();
		}
		else if (deck.equals(Constants.DISCARD_DECK))
		{
			discard.shuffle();
		}
		else if (deck.equals(Constants.HAND))
		{
			hand.shuffle();
		}
		else if (deck.equals(Constants.PLAY_SPACE))
		{
			playSpace.shuffle();
		}
		else
		{
			System.out.println("ERROR: Wrong deck given to shuffle!");
			System.exit(1);
		}
	}

	private void shuffleInDiscard() {
		if (!library.isEmpty())
		{
			System.out.println("ERROR: Trying to shuffle in discard while library is not empty!");
			System.exit(1);
		}
		else
		{
			library.addToDeck(discard.getList());
			discard.removeAll();
			library.shuffle();
		}
	}

	public String getName() {
		return name;
	}

	public void setActions(int actions) {
		this.actions = actions;
	}

	public int getActions() {
		return actions;
	}

	public void setMoney(int money) {
		this.money = money;
	}

	public int getMoney() {
		return money;
	}

	public void setBuys(int buys) {
		this.buys = buys;
	}

	public int getBuys() {
		return buys;
	}

	public void setNewTurn() {
		actions = 1;
		buys = 1;
		money = 0;
	}

	public void changeAction(int change) {
		actions = actions + change;
		if (actions < 0)
		{
			System.out.println("ERROR: Actions are now less than 0!");
			System.exit(1);
		}
	}

	public void changeMoney(int change) {
		money = money + change;
		if (money < 0)
		{
			System.out.println("ERROR: Money is now less than 0!");
			System.exit(1);
		}
	}

	public void changeBuys(int change) {
		buys = buys + change;
		if (buys < 0)
		{
			System.out.println("ERROR: Buys are now less than 0!");
			System.exit(1);
		}
	}

	public String printLib() {
		return library.toString();
	}

	public String printDiscard() {
		return discard.toString();
	}

	public String printHand() {
		return hand.toString();
	}

	public String printPlaySpace() {
		return playSpace.toString();
	}

	public String toString() {
		return "Player ID: " + name;
	}

	public Deck getHand() {
		return hand;
	}

	public Deck getLib() {
		return library;
	}

	public Deck getDiscard() {
		return discard;
	}

	public Deck getPlaySpace() {
		return playSpace;
	}

	public int getVictoryPoints() {
		int totalCards = library.size() + hand.size() + discard.size();
		int gardensPoints = totalCards / 10;
		return library.getVictoryPoints(gardensPoints) + hand.getVictoryPoints(gardensPoints)
				+ discard.getVictoryPoints(gardensPoints);
	}

	public boolean hasCounter() {
		return hand.hasCounter();
	}

	public boolean equals(Object obj) {
		boolean equals;
		if (obj == null || !(obj instanceof Player))
		{
			equals = false;
		}
		else
		{
			Player other = (Player) obj;
			if (this.name.equals(other.name))
			{
				equals = true;
			}
			else
			{
				equals = false;
			}
		}
		return equals;
	}
}
